<?php
namespace app\scodetrace\model;

use \app\scodetrace\encoder\PcodeEncoder;
use \app\scodetrace\encoder\TcodeEncoder;

class Pcode extends \app\common\model\Base {
  protected $table = 'xl_pcode';

  /**
   * this interface used for add a new Pcode to database,this function will allocate a new Pcode
   * @param Array $ids a set of ids will be submitted
   * @param Boolean $isScode if it is set to true,the function treat the id as scode id.if it is set to false,the function will treat the ids as pcode.
   * @param Boolean $force this function will ignore already allocate scode by default,you have to set $force to true to force unbind the old pcode binding,and bind the new pcode.
   * @return Array|int|false if the function execute successfully, will return an integer,it means the new id(pcode),if the parameter is checked wrongly,the function will return false,and the error message will turn back in model->error,you can use $modelObj->getError() to get it.if the ids exists conflict in the data, the function will return an Array, the Array contain the errmsg and which one is wrong.
   */
  public function createPcode($ids, $isScode = true, $force=false) {
    if (!is_array($ids)){
      $this->error = 'ids必须为数组';
      return false;
    }
     if (!count($ids)) {
      $this->error = 'ids必须包含内容';
      return false;
    }

    if ($isScode) {
      $obj = model('Scode')->select($ids);
      if (count($obj)!=count($ids)) {
        return ['ids' => $obj->where('id','not in',$ids),'errmsg' => '存在无效的防伪码'];
      }
      if (count($illegal = $obj->where('pack_id','<>',0))) {
        if ($force) {
          $this->unbindScode($ids);
        } else {
          return ['ids' => $illegal->column('id'),'errmsg' => '存在已装箱的防伪码'];
        }
      }
    } else {
      $obj = $this->select($ids);
      if ($illegal = $obj->where('pid','<>',0)) {
        if ($force) {
          $this->unbindPcode($ids);
        } else {
          return ['ids' => $illegal->column('id'),'errmsg' => '存在已装箱的装箱码'];
        }
      }
    }
    if (!$this->save(['content'=>implode(',', $ids),'pid'=>0,'type'=>$isScode?0:1])){
      $this->error = '创建装箱码失败';
    } else {
      $id = $this->getAttr('id');
      model('Scode')->update(['pack_id' => $id],['id' => $ids]);
      return $id;
    }
  }

  /**
   * unbind the scode and its pack code,the ids you push must be the id in the xl_scode table.
   * this function will find the pcode relating to the ids you specify and unbind it.
   * @param  Array $ids scode ids to be unbound
   * @return Boolean      if the function execute successfully,the function will return true.
   */
  public function unbindScode($ids) {
    $objs = $this->where('id','in',function($query) {
      $query->table('xl_scode')->where('id','in',$ids);
    })->select();
    foreach($objs as $obj) {
      $tmp = explode(',',$obj->getAttr('content'));
      if(!$tmp)
        continue;
      $tmp = array_diff($tmp,$ids);
      if (count($tmp)) {
        $tmp = implode(',', $tmp);
      } else {
        $tmp = null;
      }
      $obj->setAttr('content',$tmp);
      $obj->save();
    }
    return true;
  }

  public function unbindPcode($ids) {
    $objs = $this->where('pid', 'in', $ids)->select();
    foreach($objs as $obj) {
      $tmp = explode(',',$obj->getAttr('content'));
      if(!$tmp)
        continue;
      $tmp = array_diff($tmp,$ids);
      if (count($tmp)) {
        $tmp = implode(',', $tmp);
      } else {
        $tmp = null;
      }
      $obj->setAttr('content',$tmp);
      $obj->save();
    }
    return true;
  }

  /**
   * [modifyPcode description]
   * @param  [type]  $ids     [description]
   * @param  string  $mode    it can be set to "append" "modify" "delete"
   *                              append will add the $ids to the pcode content,
   *                              modify will check the difference between the database and the $ids,and do sync.finally, the content will be set to $id.
   *                              delete will delete the ids from this pcode content.if the id cannot be found in the pcode content, it will be skipped.
   * @param Boolean $isScode if it is set to true,the function treat the id as scode id.if it is set to false,the function will treat the ids as pcode.
   * @param Boolean $force this function will ignore already allocate scode by default,you have to set $force to true to force unbind the old pcode binding,and bind the new pcode.
   * @return [type]           [description]
   */
  public function modifyPcode($ids,$mode = 'append',$isScode=true,$force=false) {

  }

  /**
   * get all scode relate to this pcode
   * @return Array all scode relate to cur scode
   */
  public function getScodeId() {
    $pcode_ids = [];
    $scode_ids = [];
    switch ($this->getAttr('type')) {
      case 1: //pcode
        $tmp_pcode = $this->getAttr('content');
        if (!$tmp_pcode) {
          return [];
        } else {
          $pcode_ids = explode(',', $tmp_pcode);
          $pcode_ids = array_merge($this->getAllChild($pcode_ids),$pcode_ids);
          $contents = $this->where([['id','in',$pcode_ids],['content','is not',null],['type','=',0]])->column('content');
          foreach ($contents as $v) {
            $scode_ids = array_merge($scode_ids, explode(',', $v));
          }
        }
      break;
      case 0: //scode
        $content = $this->getAttr('content');
        if (!$content) {
          return [];
        } else {
          $scode_ids = explode(',', $content);
        }
      break;
    }
    return $scode_ids;
  }

}
?>